package com.bawei.es.service.impl;

import com.bawei.common.core.domain.R;
import com.bawei.domain.request.DocInfoReq;
import com.bawei.domain.query.DocQueryReq;
import com.bawei.domain.request.DocUpdReq;
import com.bawei.es.service.EsDocService;
import com.bawei.es.service.EsIndexService;
import lombok.extern.log4j.Log4j2;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.Map;

@Service
@Log4j2
public class EsDocServiceImpl implements EsDocService {


    @Autowired
    private RestHighLevelClient restHighLevelClient;


    @Autowired
    private EsIndexService esIndexService;


    @Override
    public R createDoc(DocInfoReq docInfoReq) {
        log.info("开始添加文档,请求参数:{}", docInfoReq);
        boolean exits = esIndexService.isExitIndex(docInfoReq.getIndexName());
        if (!exits) {
            throw new RuntimeException("索引不存在");
        }
        List<Map<String, Object>> datas = docInfoReq.getDatas();
        if (datas == null || datas.isEmpty()) {
            throw new RuntimeException("文档数据为空");
        }
        //校验datas是否为空
        for (Map<String, Object> data : datas) {
            IndexRequest indexRequest = new IndexRequest(docInfoReq.getIndexName());
            if (docInfoReq.getIdField() != null && docInfoReq.isNeedId() && data.containsKey(docInfoReq.getIdField())) {
                String docId = data.get(docInfoReq.getIdField()).toString();
                try {
                    IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
                    String index = indexResponse.getIndex();
                    String id = indexResponse.getId();
                    if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
                        log.info("文档创建成功:{}{}", index, id);
                    }

                    if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
                        log.info("文档修改成功:{}{}", index, docId);
                    }
                } catch (IOException e) {
                    throw new RuntimeException("文档创建失败", e);
                }
            }
        }
        return R.ok("文档创建成功");
    }

    @Override
    public void deleteDoc(String id, String indexName) {
        boolean exits = esIndexService.isExitIndex(indexName);
        if (!exits) {
            throw new RuntimeException("索引不存在");
        }
        DeleteRequest deleteRequest = new DeleteRequest(id);

        try {
            DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
            if (deleteResponse.getResult() == DocWriteResponse.Result.NOT_FOUND) {
                throw new RuntimeException("没有要删除的文档");
            } else if (deleteResponse.getResult() == DocWriteResponse.Result.DELETED) {
                log.info("文档删除成功:{}", deleteResponse.getId());
            } else {
                throw new RuntimeException("没有能够成功删除文档");
            }

        } catch (IOException e) {
            throw new RuntimeException("删除文档出现问题", e);
        }
    }


    @Override
    public Object queryIndex(DocQueryReq docQueryReq) {
        SearchRequest searchRequest = new SearchRequest(docQueryReq.getIndexName());
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.multiMatchQuery(docQueryReq.getKeyword(), docQueryReq.getQueryFields().toArray(new String[0])));
        //设置分页
        Integer pageNum = docQueryReq.getPageNum();
        Integer pageSize = docQueryReq.getPageSize();
        searchSourceBuilder.from((pageNum - 1) * pageSize);
        searchSourceBuilder.size(pageSize);
        if ("desc".equals(docQueryReq.getSortType())) {
            searchSourceBuilder.sort(SortBuilders.fieldSort(docQueryReq.getSortField()).order(SortOrder.DESC));
        } else {
            searchSourceBuilder.sort(SortBuilders.fieldSort(docQueryReq.getSortField()).order(SortOrder.ASC));
        }
        //返回字段
        searchSourceBuilder.fetchSource(docQueryReq.getQueryFields().toArray(new String[0]), null);
        try {
            restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return null;
    }


    @Override
    public void updateDoc(DocUpdReq docUpdReq) {
        boolean exits = esIndexService.isExitIndex(docUpdReq.getIndexName());
        if (!exits) {
            throw new RuntimeException("索引不存在");
        }
        UpdateRequest updateRequest = new UpdateRequest(docUpdReq.getIndexName(), docUpdReq.getId()).doc(docUpdReq.getUpdateFields());
        try {
            UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
            if (update.getResult() == DocWriteResponse.Result.UPDATED) {
                log.info("成功更新的文件: {}", update.getId());
            } else {
                throw new RuntimeException("未能更新文档");
            }
        } catch (IOException e) {
            throw new RuntimeException("更新文档报错 " + e.getMessage());
        }

    }


}
